package com.alan.product.issue.service.impl;

import com.alan.product.issue.entity.Order;
import com.alan.product.issue.exception.ParamErrorException;
import com.alan.product.issue.mapper.OrderMapper;
import com.alan.product.issue.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;

@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    private OrderService self;

    @Autowired
    private OrderMapper orderMapper;

    @Override
    public String createOrder(Order order) {
        // 1. 检查参数、权限等是否合法
        // 2. 对收件地址进行解析
        CompletableFuture<String> parseAddressFuture = CompletableFuture.supplyAsync(
                () -> remoteParseAddress(
                        order.getReceiverProvince(),
                        order.getReceiverCity(),
                        order.getReceiverCounty(),
                        order.getReceiverDetailAddress())
        );
        // 3. 对收件人手机号进行加密
        CompletableFuture<String> encryptReceiverPhoneFuture = CompletableFuture.supplyAsync(
                () -> remoteEncrypt(order.getReceiverPhone()));
        // 4. 对收件人详细地址进行加密
        CompletableFuture<String> encryptReceiverAddressFuture = CompletableFuture.supplyAsync(
                () -> remoteEncrypt(order.getReceiverDetailAddress()));
        // 5. 对寄件人手机号进行加密
        CompletableFuture<String> encryptSenderPhoneFuture = CompletableFuture.supplyAsync(
                () -> remoteEncrypt(order.getSenderPhone()));
        // 6. 对寄件人详细地址进行加密
        CompletableFuture<String> encryptSenderAddressFuture = CompletableFuture.supplyAsync(
                () -> remoteEncrypt(order.getSenderDetailAddress()));
        // 7. 获取运单号
        CompletableFuture<String> getMailNoFuture = CompletableFuture.supplyAsync(
                () -> remoteGetMailNo(order.getOrderNo()));

        try {
            order.setNetCode(parseAddressFuture.get());
            order.setReceiverPhone(encryptReceiverPhoneFuture.get());
            order.setReceiverDetailAddress(encryptReceiverAddressFuture.get());
            order.setSenderPhone(encryptSenderPhoneFuture.get());
            order.setSenderDetailAddress(encryptSenderAddressFuture.get());
            order.setMailNo(getMailNoFuture.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

        // orderMapper.save(order);

        return "success";
    }

    private void check(Order order) {
        // 检查必填、手机号格式等，也可用validation注解方式搞定
        // 检查权限
    }

    private String remoteParseAddress(String province, String city, String county, String address) {
        // 远程调用公司统一地址解析服务
        LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(200));
        return "755B";
    }

    private String remoteEncrypt(String str) {
        // 远程调用公司统一加密服务
        LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(100));
        return str;
    }

    private String remoteGetMailNo(String orderNo) {
        // 远程调用公司统一运单服务
        LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(500));
        return "YT001";
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String batchCreateOrder(List<Order> orderList) {

        System.out.println("batch: " + Thread.currentThread().getName());

        orderList.parallelStream().forEach(o->self.create(o));

        return "success";
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void create(Order order) {

        System.out.println("create: " + Thread.currentThread().getName());

        if (order.getOrderNo().equals("002")) {
            throw new ParamErrorException("跨线程事务演示");
        }
        orderMapper.insert(order);
    }
}
